package mac10.roles;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;

import mac10.models.Cell;
import mac10.models.WorldModel;

public class MasterExplorer {
	private static LinkedList<Cell> expPoints;
	private static LinkedList<Cell> setExpPoints;
	private static WorldModel world;
	private static int lastStep = -1;

	public static int getLastStep() {
		return lastStep;
	}

	public static void setLastStep(int lastStep) {
		MasterExplorer.lastStep = lastStep;
	}

	public static void initiateMasterExplorer(WorldModel worldmodel) {
		MasterExplorer.expPoints = createExpPoints(worldmodel);
		MasterExplorer.setExpPoints = new LinkedList<Cell>();
		MasterExplorer.world = worldmodel;
	}

	public static LinkedList<Cell> createExpPoints(WorldModel worldmodel) {
		LinkedList<Cell> waypoints = new LinkedList<Cell>();
		int x = worldmodel.getWidth();
		int y = worldmodel.getHeight();
		x -= 2;
		y -= 2;
		while (y >= 0) {
			waypoints.addLast(worldmodel.getCell(x, y));
			// System.out.println(x+" , "+y);
			if (x > 2)
			{
				x -= 3;
			}
			else if (x == 2)
			{
			    waypoints.addLast(worldmodel.getCell(0, y));
				y -= 3;
				x = worldmodel.getWidth()-2;
			}
			else
            {
			    y -= 3;
                x = worldmodel.getWidth()-2;
            }
		}
		if (y == -1)
		{
		    x = worldmodel.getWidth()-2;
		    y = 0;
		    while (x >= 0)
		    {
		        waypoints.addLast(worldmodel.getCell(x, y));
	            // System.out.println(x+" , "+y);
	            x -= 3;
		    }
		    if (x == -1)
		        waypoints.addLast(worldmodel.getCell(0, 0));
		}
		
		return waypoints;
	}

	public static synchronized Cell nextUnknownCell(Cell agent, int step) {
		if (MasterExplorer.lastStep != step)
		{
			MasterExplorer.setExpPoints = new LinkedList<Cell>();
			MasterExplorer.lastStep = step;
		}

		int distance = Integer.MAX_VALUE;
		Cell erg = agent;
		for (Cell cell : expPoints) {
			if (WorldModel.getDistance(agent, cell) < distance
					&& !MasterExplorer.setExpPoints.contains(cell)) {
				erg = cell;
				distance = WorldModel.getDistance(agent, cell);
			}

		}
		MasterExplorer.setExpPoints.add(erg);
		return erg;
	}
	// mode true filter known, false filter new
	public static void filterKnownPoints(WorldModel model, boolean mode)
	{
		MasterExplorer.world = model;
		LinkedList<Cell> newExpPoints = new LinkedList<Cell>();
		for (Iterator<Cell> iterator = expPoints.iterator(); iterator.hasNext();) {
			Cell cell = (Cell) iterator.next();
			if (areaKnown(cell) && mode)
			{
				iterator.remove();
			}
			else if (areaNew(cell, 50) && !mode)
			{
				iterator.remove();
			}
			else if (cell.isObstacle() || cell.isSwitch())
			{
			    iterator.remove();
			    ArrayList<Cell> list = world.getNeighbours(cell.getX(), cell.getY());

		        for (Cell cell2 : list) {
		            if (cell2.isUnknown())
		                newExpPoints.add(cell2);
		        }
			}
		}
		
		expPoints.addAll(newExpPoints);
	}

	public static boolean areaKnown(Cell cell) {
		ArrayList<Cell> list = world.getNeighbours(cell.getX(), cell.getY());

		for (Cell cell2 : list) {
			if (cell2.isUnknown())
				return false;
		}

		return true;
	}
	
	public static boolean areaNew(Cell cell, int step) {
		ArrayList<Cell> list = world.getNeighbours(cell.getX(), cell.getY());

		for (Cell cell2 : list) {
			if (WorldModel.staticWorldModel.getCurrStep() - cell2.getTimestamp() > step)
				return false;
		}

		return true;
	}
	
	public static int getNumberOfUnexploredPoints(){
		return expPoints.size();
	}

	/**
	 * @return the expPoints
	 */
	public static LinkedList<Cell> getExpPoints()
	{
		return expPoints;
	}

	/**
	 * @param expPoints the expPoints to set
	 */
	public static void setExpPoints(LinkedList<Cell> expPoints)
	{
		MasterExplorer.expPoints = expPoints;
	}
}
